/**
@file combinationstester.cpp
@brief Combinations automated tests implementation

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 3 of the License.

@author VestniK (Sergey N.Vidyuk)
 */
#include "combinationstester.h"

#include <QtTest/QtTest>

#include "tile.h"
#include "abscombination.h"
#include "tilespair.h"
#include "chou.h"
#include "defaults.h"
#include "mjnexceptions.h"

using namespace mjn;

void CombinationsTester::BaseFunctionalityTests() {
   TilesPair pair;
   // Just random tiles
   Tile t1(Tile::Dot, (Tile::TileRanks)1);
   Tile t2(Tile::Bamboo, (Tile::TileRanks)5);
   Tile t3(Tile::Dragon, Tile::Red);
   Tile t4(Tile::Dragon, Tile::Red);
   //Test 1
   qDebug("Test of ability to add up to CombinationSize tiles:");
   QVERIFY2( pair.addTile(t1),"Can't add tile" );
   QVERIFY2( pair.addTile(t2),"Can't add tile" );
   QVERIFY2( ! pair.addTile(t3),"Can add to many tiles" );
   QCOMPARE( pair.getTilesCount() , pair.getCombinationSize() );
   qDebug("\tOk");
   // Test 2
   qDebug("Test of correct score and multiplication factor calculation for invalid combination:");
   QVERIFY2( !pair.isValid(),"Combination is valid. Maybe error in code of this test." );
   QCOMPARE( pair.score(West,East) , (unsigned)0 );
   QCOMPARE( pair.multiplyFactor(West,East) , (unsigned)1 );
   qDebug("\tOk");
   // Test 3
   pair.clear();
   pair.addTile(t3);
   pair.addTile(t4);
}

void CombinationsTester::TilesPairTests() {
   TilesPair pair;
   Tile t0(Tile::Dot, (Tile::TileRanks)3);
   Tile t1(Tile::Dot, (Tile::TileRanks)3);
   Tile t2(Tile::Wind, Tile::East);
   Tile t3(Tile::Wind, Tile::East);
   Tile t4(Tile::Dragon, Tile::Green);
   Tile t5(Tile::Dragon, Tile::Green);
   // Test 1
   qDebug("Test of validation function:");
   pair.addTile(t1);
   pair.addTile(t2);
   QVERIFY( !pair.isValid() );
   pair.clear();
   pair.addTile(t2);
   pair.addTile(t3);
   QVERIFY( pair.isValid() );
   pair.clear();
   qDebug("\tOk");
   // Test 2
   qDebug("Test of score calculation:");
   pair.addTile(t0);
   pair.addTile(t1);
   QCOMPARE( pair.score(East,East),(unsigned)0 );
   QCOMPARE( pair.multiplyFactor(East,East),(unsigned)1 );
   pair.clear();
   pair.addTile(t4);
   pair.addTile(t5);
   QCOMPARE( pair.score(East,East),(unsigned)2 );
   QCOMPARE( pair.multiplyFactor(East,East),(unsigned)1 );
   pair.clear();
   pair.addTile(t2);
   pair.addTile(t3);
   QCOMPARE( pair.score(East,East),(unsigned)2 );
   QCOMPARE( pair.multiplyFactor(East,East),(unsigned)1 );
   QCOMPARE( pair.score(East,West),(unsigned)2 );
   QCOMPARE( pair.multiplyFactor(East,East),(unsigned)1 );
   QCOMPARE( pair.score(North,East),(unsigned)2 );
   QCOMPARE( pair.multiplyFactor(East,East),(unsigned)1 );
   QCOMPARE( pair.score(West,South),(unsigned)0 );
   QCOMPARE( pair.multiplyFactor(East,East),(unsigned)1 );
   qDebug("\tOk");
}

void CombinationsTester::ChouTests() {
   Chou chou;
   // Test 1
   qDebug("Testing simple valid chou validation:");
   Tile t1(Tile::Dot, (Tile::TileRanks)1);
   Tile t2(Tile::Dot, (Tile::TileRanks)2);
   Tile t3(Tile::Dot, (Tile::TileRanks)3);
   chou.addTile(t1);
   chou.addTile(t2);
   chou.addTile(t3);
   QVERIFY2( chou.isValid() , "Correct chou decidet to be incorrect" );
   qDebug("\tOk");
   // Test 2
   qDebug("Testing for braking valid combination by mixing types:");
   chou.clear();
   t3 = Tile( Tile::Bamboo, (Tile::TileRanks)3);
   chou.addTile(t1);
   chou.addTile(t2);
   chou.addTile(t3);
   QVERIFY2( ! chou.isValid() , "Invalid chou decided to be valid" );
   chou.clear();
   t2 = Tile( Tile::Character, (Tile::TileRanks)2 );
   chou.addTile(t1);
   chou.addTile(t2);
   chou.addTile(t3);
   QVERIFY2( ! chou.isValid() , "Invalid chou decided to be valid" );
   qDebug("\tOk");
   // Test 3
   qDebug("Test for combination with not numbered tiles is not chou:");
   chou.clear();
   t1 = Tile( Tile::Dragon, Tile::White);
   t2 = Tile( Tile::Dragon, Tile::Green);
   t3 = Tile( Tile::Dragon, Tile::Red);
   chou.addTile(t1);
   chou.addTile(t2);
   chou.addTile(t3);
   QVERIFY2( ! chou.isValid() , "Invalid chou decided to be valid" );
   qDebug("\tOk");
   // Test 4
   qDebug("Test for correct chou validation on all numbered combinations:");
   for ( int i = MIN_TILE_NUMBER; i <= MAX_TILE_NUMBER; i++ ) {
      for ( int j = i; j <= MAX_TILE_NUMBER; j++ ) {
         for ( int k = j; k<= MAX_TILE_NUMBER; k++ ) {
            bool expected;
            if ( (j == i+1) && (k == j+1) ) {
               expected = true;
            } else {
               expected = false;
            }
            chou.clear();
            t1 = Tile(Tile::Character, (Tile::TileRanks)i);
            t2 = Tile(Tile::Character, (Tile::TileRanks)j);
            t3 = Tile(Tile::Character, (Tile::TileRanks)k);
            // ---------
            chou.addTile(t1);
            chou.addTile(t2);
            chou.addTile(t3);
            QCOMPARE( chou.isValid() , expected );
            QCOMPARE( chou.score(East,East),(unsigned)0 );
            QCOMPARE( chou.multiplyFactor(East,East),(unsigned)1 );
            // ----------
            chou.clear();
            chou.addTile(t1);
            chou.addTile(t3);
            chou.addTile(t2);
            QCOMPARE( chou.isValid() , expected );
            QCOMPARE( chou.score(East,East),(unsigned)0 );
            QCOMPARE( chou.multiplyFactor(East,East),(unsigned)1 );
            // ----------
            chou.clear();
            chou.addTile(t2);
            chou.addTile(t1);
            chou.addTile(t3);
            QCOMPARE( chou.isValid() , expected );
            QCOMPARE( chou.score(East,East),(unsigned)0 );
            QCOMPARE( chou.multiplyFactor(East,East),(unsigned)1 );
            // ----------
            chou.clear();
            chou.addTile(t3);
            chou.addTile(t1);
            chou.addTile(t2);
            QCOMPARE( chou.isValid() , expected );
            QCOMPARE( chou.score(East,East),(unsigned)0 );
            QCOMPARE( chou.multiplyFactor(East,East),(unsigned)1 );
            // ----------
            chou.clear();
            chou.addTile(t2);
            chou.addTile(t3);
            chou.addTile(t1);
            QCOMPARE( chou.isValid() , expected );
            QCOMPARE( chou.score(East,East),(unsigned)0 );
            QCOMPARE( chou.multiplyFactor(East,East),(unsigned)1 );
            // ----------
            chou.clear();
            chou.addTile(t3);
            chou.addTile(t2);
            chou.addTile(t1);
            QCOMPARE( chou.isValid() , expected );
            QCOMPARE( chou.score(East,East),(unsigned)0 );
            QCOMPARE( chou.multiplyFactor(East,East),(unsigned)1 );
            // ----------
         }
      }
   }
   qDebug("\tOk");
}
